package logAccessor

import (
	"context"
	"encoding/json"
	"fmt"
	"grpc.getaway.adminspro.padmins.com/pkg/config"
	"grpc.getaway.adminspro.padmins.com/pkg/libs/log"
	"grpc.getaway.adminspro.padmins.com/pkg/libs/utils"
	"io"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"
	"time"
)

var logConfig *log.LogConfig

func NewLogger(ctx context.Context, prefix string) log.Logger {
	return log.NewLogger(ctx, prefix, logConfig)
}

func init() {
	w, _ := os.OpenFile(os.DevNull, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	logConfig = log.NewLogConfig(w)
	logConfig.SetLevel(log.Level(config.Config.Log.Level))
	logConfig.SetDateLayout("Y-m-dTH:i:s.u")
	if config.Config.Log.Filename != "" {
		dateMatch := regexp.MustCompile(`\{(.*?)\}`).FindAllStringSubmatch(config.Config.Log.Filename, -1)
		logConfig.SetWriter(func(ctx context.Context) (io.Writer, error) {
			filename := config.Config.Log.Filename
			for _, r := range dateMatch {
				// 替换日期
				filename = strings.ReplaceAll(filename, r[0], utils.Date(r[1]))
			}
			dirname := filepath.Dir(filename)
			if err := os.MkdirAll(dirname, 0755); err != nil {
				return nil, fmt.Errorf("failed to create directory %s: %s", dirname, err)
			}
			fh, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)

			if err != nil {
				return nil, fmt.Errorf("failed to open file %s: %s", filename, err)
			}
			return fh, nil
		})
	}
	logConfig.SetFormatter(func(_ context.Context, record *log.Record) string {
		row, _ := json.Marshal(record)
		return string(row)
	})

	logConfig.PushProcessor(func(ctx context.Context, record *log.Record) {
		if record.Level != log.LevelName[log.ErrorLevel] {
			return
		}
		_, file, line, ok := runtime.Caller(3)
		if !ok {
			file = "???"
			line = 0
		}
		record.Extra["file"] = fmt.Sprintf("%s:%d", file, line)
	})

	logConfig.PushProcessor(func(ctx context.Context, record *log.Record) {

		if runtime, ok := utils.ExtraRuntime(ctx); ok {
			record.Extra["runtime"] = fmt.Sprintf("%v", time.Since(time.Time(runtime)))
		}

		if traceId, ok := utils.ExtraTraceId(ctx); ok {
			record.Extra["trace_id"] = traceId
		}

		if requestId, ok := utils.ExtraRequestId(ctx); ok {
			record.Extra["request_id"] = requestId
		}

		record.Extra["pid"] = os.Getpid()
	})
}
